﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace FictionsDownload.DAL
{
    public class BaseEfDAL : IDAL
    {
        #region 变量

        protected DbContext context;
        #endregion

        #region 构造函数

        public BaseEfDAL(DbContext dbcontext)
        {
            context = dbcontext;
        }
        #endregion

        #region IRepository

        public IQueryable<T> All<T>() where T : class
        {
            return context.Set<T>().AsNoTracking();
        }

        public void Update<T>(T entity) where T : class
        {
            var entry = context.Entry(entity);
            if (entry.State == EntityState.Detached)
            {
                context.Set<T>().Attach(entity);
            }
            entry.State = EntityState.Modified;
        }

        public void Insert<T>(T entity) where T : class
        {
            context.Set<T>().Add(entity);
        }

        public void Delete<T>(T entity) where T : class
        {
            var entry = context.Entry(entity);
            if (entry.State == EntityState.Detached)
            {
                context.Set<T>().Attach(entity);
            }
            entry.State = EntityState.Deleted;
            context.Set<T>().Remove(entity);
        }

        public void Delete<T>(Expression<Func<T, bool>> conditions) where T : class
        {
            var list = All<T>().Where(conditions);
            foreach (var item in list)
            {
                Delete<T>(item);
            }
        }

        
        public T Find<T>(object Id) where T : class
        {
            if (Id == null)
                throw new Exception("Find不允许传入空Id");
            return context.Set<T>().Find(Id);
        }
        public IQueryable<T> Set<T>() where T : class
        {
            return context.Set<T>();
        }


        public List<T> SqlQuery<T>(string sql)
        {
            return context.Database.SqlQuery<T>(sql).ToList();
        }


        public int ExecuteSqlCommand(string sql)
        {
            return context.Database.ExecuteSqlCommand(sql);
        }

        public int SaveChanges()
        {
            return context.SaveChanges();
        }

        public void Dispose()
        {
            context.Dispose();
        }

        public long GetNextSequenceValue(string sequenceName)
        {
            var rawQuery = context.Database.SqlQuery<long>(string.Format("SELECT NEXT VALUE FOR {0}", sequenceName)).ToList();
            long nextVal = rawQuery.Single();

            return nextVal;
        }

        public List<T> GetList<T>(Expression<Func<T, bool>> conditions = null) where T : class
        {
            if(conditions == null)
            {
                return All<T>().ToList();
            }
            else
            {
                return All<T>().Where(conditions).ToList();
            }
        }

        public List<T> GetList<T, S>(Expression<Func<T, bool>> conditions, Expression<Func<T, S>> orderBy, int pageSize, int pageIndex, out int totalCount) where T : class
        {
            var queryList = All<T>().Where(conditions);
            totalCount = queryList.Count();
            return queryList.OrderByDescending(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
        }
        #endregion
    }
}
